package com.apes.fn.scm.retailOrder.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.fn.business.fixedLoss.repository.LossQuotationRepository;
import com.apes.fn.crm.customerExpand.FnCustomerExpand;
import com.apes.fn.scm.contract.FnContract;
import com.apes.fn.scm.contract.FnContractRepository;
import com.apes.fn.scm.retailOrder.model.RetailOrder;
import com.apes.fn.scm.retailOrder.model.RetailOrderExtension;
import com.apes.fn.scm.retailOrder.model.RetailOrderItem;
import com.apes.fn.scm.retailOrder.model.RetailOrderPayMethod;
import com.apes.fn.scm.retailOrder.repository.*;
import com.apes.fn.scm.retailOrder.service.retailProcess.RetailProcess;
import com.apes.fn.scm.retailOrder.service.retailProcess.RetailProcessFactory;
import com.apes.fn.scm.retailOrder.service.tc.commission.EmployeeCommissionService;
import com.apes.fn.server.productReceive.ProductReceiveItem;
import com.apes.fn.server.productReceive.ProductReceiveItemRepository;
import com.apes.fn.server.productReturn.ProductReturn;
import com.apes.fn.server.productReturn.ProductReturnItem;
import com.apes.fn.server.servicePlan.model.ServicePlan;
import com.apes.fn.server.servicePlan.model.ServicePlanItem;
import com.apes.fn.server.servicePlan.repository.ServicePlanItemRepository;
import com.apes.fn.server.servicePlan.repository.ServicePlanRepository;
import com.apes.fn.server.servicePlan.service.ServicePlanceService;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.plugin.esb.processor.idempotent.AntiHeavy;
import com.apes.framework.plugin.esb.processor.idempotent.AntiHeavyRepository;
import com.apes.framework.plugin.event.Listener;
import com.apes.framework.util.DateUtil;
import com.apes.framework.util.MapUtil;
import com.apes.scm.account.account.model.InventoryBatch;
import com.apes.scm.account.account.repository.InventoryBatchRepository;
import com.apes.scm.account.account.service.ProductAccountService;
import com.apes.scm.account.ledger.service.LedgerService;
import com.apes.scm.invoice.model.Invoice;
import com.apes.scm.invoice.repository.InvoiceRepository;
import com.apes.scm.masterdata.frame.model.Dept;
import com.apes.scm.masterdata.frame.repository.DeptRepository;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.masterdata.party.repository.PartyRoleRepository;
import com.apes.scm.stock.transfer.model.Pick;
import com.apes.scm.stock.transfer.model.PickItem;
import com.apes.scm.voucher.service.VoucherType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.groupingBy;

/**
 * 功能：销售订单服务
 *
 * @author xul
 * @create 2018-04-03 16:56
 */
@Service("retailService")
public class RetailService extends DomainService {

    @Autowired
    private RetailOrderRepository orderRepository;
    @Autowired
    private ProductAccountService productAccountService;
    @Autowired
    private ServicePlanItemRepository servicePlanItemRepository;
    @Autowired
    private LedgerService ledgerService;
    @Autowired
    private DeptRepository deptRepository;
    @Autowired
    private InvoiceRepository invoiceRepository;
    @Autowired
    private RetailOrderPayMethodRepository retailOrderPayMethodRepository;
    @Autowired
    private EmployeeCommissionService employeeCommissionService;
    @Autowired
    private ServicePlanRepository servicePlanRepository;
    @Autowired
    private LossQuotationRepository lossQuotationRepository;
    @Autowired
    private RetailOrderDao retailOrderDao;

    /**
     * 未使用
     * 功能：创建订单
     */
    public RetailOrder create(SimpleRequest request) {
        RetailOrder saleOrder = request.getO(RetailOrder.class);
        saleOrder.setState("sent");
        saleOrder.setInvoiceStatus("no");
        saleOrder.computeAmt(); // 合计金额

        RetailOrder saleOrderNew = orderRepository.saveAndFlush(saleOrder);

        //占用可用数
        setProductAvailable(saleOrderNew, -1, "零售订单生成");
        return saleOrderNew;
    }


    public RetailOrder createRetailOrder(SimpleRequest request){
        RetailOrder saleOrder = request.getO(RetailOrder.class);
        if (StringUtils.isEmpty(saleOrder.getOrigin())) throw new RuntimeException("没有传入 Origin 字段！");
        RetailOrder order = orderRepository.findByOrigin(saleOrder.getOrigin());
        if (order != null) return order;

        // 增加幂等控制，数据库建议唯一索引
        AntiHeavy antiHeavy = new AntiHeavy();
        antiHeavy.setId("retail.order.createAndapprove:"+ saleOrder.getOrigin());
        SpringManager.getBean(AntiHeavyRepository.class).save(antiHeavy);

        saleOrder.setCompany(saleOrder.getDept().getCompany());
        saleOrder.setState("sent");
        saleOrder.setInvoiceStatus("no");
        saleOrder.computeAmt();  // 合计金额, 检查明细金额

        RetailProcess retailProcess = RetailProcessFactory.get(saleOrder.getOrderType());

        /* 第一步：保存之前做相应的处理 */
        retailProcess.beforeSave(saleOrder);

        /* 第二步： 客户信息保存  */
        saleOrder.setCustomerExpand(saveCustomerInfo(request.getS()));

        /* 保存 */
        saleOrder = orderRepository.saveAndFlush(saleOrder);

        saleOrder.setState("confirmed");
        saleOrder.setDateApprove(new Date());
        saleOrder.setApproveUID(getPerson(request));

        /* 第三步：保存之后做相应的处理 */
        retailProcess.afterSave(saleOrder);

        /* 第四步：公共处理部分 */
        retailProcess.afterCommonProcess(saleOrder);
        setShipped(saleOrder);    // 明细有可能全部不用发货, 设置零售单的状态

        return saleOrder;
}

    private FnCustomerExpand saveCustomerInfo(String string){
        JSONObject json = JSONObject.parseObject(string);
        return this.invoke("fn.customerExpand.updateOrInsert", MapUtil.mapper(
                "customerExpand", null, "customer", json.get("customerInfo"), "customerCar", json.get("customerCar")));
    }

    /**
     * 测试使用获取商品规则
     * @param request
     * @return
     */
    public int getProductRule(SimpleRequest request) {
        String saleOrderItemId = request.get("id");
        RetailOrderItem retailOrderItem = SpringManager.getBean(RetailOrderItemRepository.class).findOne(saleOrderItemId);
        ServicePlanItem servicePlanItem = servicePlanItemRepository.findOne(retailOrderItem.getOriginnumber());
        return servicePlanItem.calcProductRule();
    }

    /**
     * 测试使用获取商品规则
     * @param request
     * @return
     */
    public int getPlanItemProductRule(SimpleRequest request) {
        String servicePlanItemId = request.get("id");
        ServicePlanItem servicePlanItem = servicePlanItemRepository.findOne(servicePlanItemId);
        return servicePlanItem.calcProductRule();
    }

    /**
     * 检查数据
     *
     * @param request
     */
    private void checkData(SimpleRequest request) {
        String id = request.get("id");
        RetailOrder order = orderRepository.findOne(id);
        if (order == null) throw new RuntimeException("订单：" + request.get("id") + " 在系统中不存在。");
        if (order.getVersion() != (int) request.get("version")) throw new RuntimeException("记录已更新或已删除，请重新提交！");
        if (order.getDeleteDate() != null) throw new RuntimeException("订单：" + request.get("id") + " 在系统中已删除！");
        if (order.getDateCancel() != null) throw new RuntimeException("订单：" + request.get("id") + " 在系统中已取消！");
        if (order.getDateApprove() != null) throw new RuntimeException("订单：" + request.get("id") + " 在系统中已审批。");
    }

    /**
     * 功能：更新零售单
     *
     * @param request
     * @return
     */
    public RetailOrder update(SimpleRequest request) {
        checkData(request);
        RetailOrder retailOrder = request.getO(RetailOrder.class);

        // 还原可用数
        RetailOrder oldRetailOrder = orderRepository.findOne(retailOrder.getId());
        setProductAvailable(oldRetailOrder, 1, "零售订单修改还原可用数");

        //占用可用数
        setProductAvailable(retailOrder, -1, "零售订单修改写入新的可用数");
        return orderRepository.saveAndFlush(retailOrder);
    }

    /**
     * 功能：删除订单
     *
     * @param request 传入数据
     * @return 返回值·
     */
    public String delete(SimpleRequest request) {
        checkData(request);
        RetailOrder saleOrder = request.getO(RetailOrder.class);

        // 还原之前的可卖数
        RetailOrder oldOrder = orderRepository.findOne(saleOrder.getId());
        setProductAvailable(oldOrder, 1, "零售订单删除");

        // 保存新的数据
        saleOrder.setState("delete");
        saleOrder.setDeleteDate(new Date());
        saleOrder.setDeleteUID(this.getPerson(request));
        orderRepository.saveAndFlush(saleOrder);
        return "删除成功！";
    }

    /**
     * 功能：审批订单
     * 功过流程编排生成交货单
     *
     * @param request
     * @return
     */
    public RetailOrder approve(SimpleRequest request) {
        checkData(request);
        RetailOrder order = request.getO(RetailOrder.class);
        order.setState("confirmed");
        order.setDateApprove(new Date());
        order.setApproveUID(getPerson(request));

        // 明细有可能全部不用发货
        RetailOrder retailOrder = setShipped(order);
        return retailOrder;
    }

    /**
     * 写入商品可用数
     *
     * @param retailOrder 零售单
     * @param type        传入 1 或者 -1
     */
    private void setProductAvailable(RetailOrder retailOrder, int type, String note) {
        retailOrder.getSaleItems().stream()
                .filter(saleItem -> saleItem.getProductRule() == 0 && saleItem.getLocation() != null)
                .forEach(
                        saleOrderItem -> productAccountService.setProductAvailable(saleOrderItem.getProduct(),
                                saleOrderItem.getLocation(), saleOrderItem.getUom(),
                                type * saleOrderItem.getProductUomQty(),
                                retailOrder.getInnerBusinessType(),
                                retailOrder.getId(), saleOrderItem.getId(),
                                note, saleOrderItem.getLocation().getCompany())
                );
    }

    // 是否需要发货
    private boolean checkPicked(RetailOrderItem retailOrderItem) {
        return retailOrderItem.getProductRule() == 0;
    }

    /**
     * 功能：创建拣配单
     * 根据仓库汇总
     *
     * @param request
     */
    public List<Pick> createPickOrder(SimpleRequest request) {
        RetailOrder order = request.getO(RetailOrder.class);
        // 定损的来源，并且非水泡车的不做处理
        if ( "DS0".equals(order.getSourceBusinessType()) ||
                ("LOSSQUOTATION".equalsIgnoreCase(order.getSourceBusinessType())) && !"RO003".equals(order.getScene().getId()) ) return new ArrayList<>();

        List<Pick> pickList = new ArrayList<>();
        //  根据明细上面的仓库进行汇总数据
        order.getSaleItems().stream()
                .filter(saleItem -> saleItem.getProductRule()==0 && saleItem.getLocation() != null)
                .collect(groupingBy(RetailOrderItem::getLocation))
                .forEach(((location, saleOrderItems) -> {

                    Set<PickItem> pickItems = new HashSet<>();
                    saleOrderItems.forEach(
                            saleItem -> {
                                PickItem pickItem = new PickItem();
                                pickItem.setProduct(saleItem.getProduct());
                                pickItem.setUom(saleItem.getUom());
                                pickItem.setOrderedQty(saleItem.getProductUomQty());
                                pickItem.setProductUomQty(saleItem.getProductUomQty());
                                pickItem.setOriginLine(saleItem.getId());
                                pickItems.add(pickItem);
                            });

                    if (pickItems.isEmpty()) return;

                    Pick pick = new Pick();
                    pick.setMoveType(order.getMoveType());
                    pick.setPartner(order.getCompany().getParty().getPatyRoleByType("Customer"));
                    pick.setLocation(location);
                    pick.setCompany(location.getCompany());     // 公司为库区的公司

                    // APP 商城直接下单的部分不自动发货
                    if (order.getServiceDept() != null && order.getSource() != null) {
                        pick.setAuto(true); // 设置自动交货
                    }

                    pick.setOrigin(order.getId());
                    pick.setOriginBusinessType(order.getInnerBusinessType());
                    pick.setOperation("deliver");               // 交货类型：交货
                    pick.setScene(order.getScene());            // 注入场景
                    pick.setPickItems(pickItems);

                    pickList.add(pick);
                }));
        return pickList;
    }

    /**
     * 功能：处理交货完成事件
     * 回写明细的交货数量
     *
     * @param request
     * @return
     */
    @Listener(topic = "event:stock.pick.delivery")
    public boolean delivery(SimpleRequest request) {
        JSONObject json = request.getJO();
        if (!json.getString("originBusinessType").equals(RetailOrder.class.getSimpleName())) return false;

        RetailOrder order = orderRepository.findOne(json.getString("origin"));
        if (order == null) return false;
        for (Map requestItem : ((List<Map>) json.get("items"))) {
            long result = order.getSaleItems().stream()
                    .filter(orderItem -> orderItem.getId().equals((String) requestItem.get("originItemId")))
                    .map(orderItem -> {
                        double qtyDone = ((Number) requestItem.get("qtyDone")).doubleValue();
                        orderItem.delivery(qtyDone);    // 设置交货数量
                        return orderItem;
                    }).count();
            if (result != 1) {
                throw new RuntimeException("零售单行号：" + requestItem.get("originItemId") + " 输入错误！");
            }
        }

        // 设置交货状态
        order.setState("delivery");
        setShipped(order);
        return true;
    }

    /**
     * 定损流程更新零售单状态
     * @param request RetailOrder
     * @return RetailOrder
     */
    public RetailOrder updateState(SimpleRequest request){
        String id = request.get("id");
        RetailOrder order = SpringManager.getBean(RetailOrderRepository.class).findOne(id);
        order.setState("vouched");
        order.setPostDate(new Date());

        // 由于存在提单冲红导致没有写完成时间
        if (Objects.isNull(order.getDateDone())) {
            order.setDateDone(new Date());
        }
        return orderRepository.saveAndFlush(order);
    }

    // 设置交货完成状态
    private RetailOrder setShipped(RetailOrder order) {
        // 更新交货状态以及单据状态
        long result = order.getSaleItems().stream()
                .filter(orderItem -> checkPicked(orderItem) && orderItem.getProductUomQty() != orderItem.getQtyDeliver())
                .count();

        // 判断是否交货完成
        if (result == 0) {
            // 交货完成
            order.setState("done");
            order.setDateDone(new Date());
            order.setShipped(true); // 交货中
        }

        return orderRepository.saveAndFlush(order);
    }

    /**
     * 分四种情况：跨公司整单内协（包括内协给车宝，赋能基地） 跨公司部门内协 公司内整单内协 公司内部分内协
     * 注意点：
     * 1. 部分内协在门店进行领用， 整单内协在基地领用（跨公司会产生一笔对门店的销售）
     * 2. 公司内整单内协在赋能基地进行归还， 跨公司整单内协无需归还
     * 3. 部分内协一律出门店库存，需做归还
     * <p>
     * 创建商品归还单
     *
     * @param request RetailOrder
     * @return List<ProductReturn>
     */
    public List<ProductReturn> createProductReturn(SimpleRequest request) {
        List<ProductReturn> productReturns = new ArrayList<>();

        RetailOrder order = request.getO(RetailOrder.class);
        //  根据明细上面的仓库进行汇总数据
        order.getSaleItems().stream()
                .filter(saleItem -> saleItem.getProductRule() == 0 && saleItem.getLocation() != null)
                .collect(groupingBy(RetailOrderItem::getLocation))
                .forEach(((location, saleOrderItems) -> {

                    List<ProductReturnItem> returnItem = new ArrayList<>();
                    saleOrderItems.forEach(
                            saleItem -> {
                                // 判断是否服务方案是跨公司整单内协
                                ServicePlanItem servicePlanItem = servicePlanItemRepository.findOne(saleItem.getOriginnumber());
                                boolean isCrossCompanyAllInnerBelongSide = servicePlanItem.getServicePlan().crossCompanyAllInnerBelongSide();
                                if (isCrossCompanyAllInnerBelongSide) return;
                                // 否则全部出自己公司的库存（包括自己和内协基地）
                                // 查询实际的领用明细
                                servicePlanItem = getRealReceiveItem(servicePlanItem);

                                List<ProductReceiveItem> productReceiveItems = SpringManager.getBean(ProductReceiveItemRepository.class).findAllByServicePlanItemId(servicePlanItem.getId());
                                double sumNotReturn = productReceiveItems.stream().mapToDouble(ProductReceiveItem::getQtyNotReturn).sum();
                                if (sumNotReturn != saleItem.getProductUomQty()) {throw new RuntimeException("零售单销售数量与领用单可归还数量不相等，商品编码："+ saleItem.getProduct().getId());}

                                productReceiveItems.stream().forEach(productReceiveItem -> {
                                    ProductReturnItem items = new ProductReturnItem();
                                    items.setProduct(productReceiveItem.getProduct());
                                    items.setUom(productReceiveItem.getUom());
                                    items.setQtyReturn(productReceiveItem.getQtyNotReturn());
                                    items.setCompany(productReceiveItem.getCompany());
                                    items.setRemark("零售单自动归还");
                                    items.setProductReceiveItem(productReceiveItem);

                                    returnItem.add(items);
                                });
                            }
                    );
                    if (returnItem.isEmpty()) return;
                    ProductReturn productReturn = new ProductReturn();
                    productReturn.setLocation(location);
                    productReturn.setCompany(location.getCompany());     // 公司为库区的公司
                    productReturn.setSource(order.getId());
                    productReturn.setSourceBusinessType(order.getClass().getSimpleName());
                    productReturn.setSourceBusinessTypeName("零售单");
                    productReturn.setProductReturnItems(returnItem);
                    productReturn.setRemark("零售单自动归还");
                    productReturns.add(productReturn);
                }));
        return productReturns;
    }


    /***
     * 获取服务方案实际的领用明细
     */
    private ServicePlanItem getRealReceiveItem(ServicePlanItem servicePlanItem) {
        ServicePlanItem realReceiveItem;
        // 查看是否存在内协（部分内协(内外)或者整单内协(公司内)））
        realReceiveItem = SpringManager.getBean(ServicePlanceService.class).findCBPForServicePlan(servicePlanItem);
        if (realReceiveItem != null) return realReceiveItem;
        return servicePlanItem;
    }

    /**
     * 更新凭证数量，查看是否全部写完凭证数量
     *
     * @param request map
     */
    @Listener(topic = "event:voucher.save.qtyVouched")
    public void setQtyVouched(SimpleRequest request) {
        JSONObject mainJson = request.getJO();
        if (!VoucherType.CUSTOMER_SALE.equals(mainJson.getString("voucherType")) ||
                !RetailOrder.class.getSimpleName().equals(mainJson.getString("businessType"))) return;

        RetailOrder retailOrder = orderRepository.findOne(mainJson.getString("id"));
        if (Objects.isNull(retailOrder)) throw new RuntimeException("更新零售单明细行凭证数量时没有找到零售单："+ mainJson.get("id") );

        retailOrder.getSaleItems().forEach( saleItem -> {
            mainJson.getJSONArray("items").forEach(x -> {
                JSONObject item = (JSONObject) x;
                if (!saleItem.getId().equals(item.getString("id"))) return;
                saleItem.setQtyVoucher(item.getDouble("qty"));

                if (item.getLong("batchId") == null) return;
                long batchId = item.getLong("batchId");
                String supplierId = item.getString("supplierId");

                if (saleItem.getSupplier() == null) {
                    PartyRole supplier = SpringManager.getBean(PartyRoleRepository.class).findById(supplierId)
                            .orElseThrow(() -> new RuntimeException("未找到供应商，编码为：" + supplierId));
                    saleItem.setSupplier(supplier);
                }

                InventoryBatch batch = SpringManager.getBean(InventoryBatchRepository.class).findById(batchId)
                        .orElseThrow(() -> new RuntimeException("未找到批次信息，编码为：" + batchId));
                saleItem.setInventoryBatch(batch);
            });
        });

        long countNum = retailOrder.getSaleItems().stream().filter(saleItem -> saleItem.getQtyVoucher() != saleItem.getProductUomQty()).count();
        if (countNum == 0) {
            retailOrder.setState("vouched");
            retailOrder.setPostDate(new Date());

            if (Objects.isNull(retailOrder.getDateDone())) {
                retailOrder.setDateDone(new Date());
            }

            orderRepository.saveAndFlush(retailOrder);
            //凭证生成,发送生成客户返利事件
            sendRetailVouched(retailOrder);
        }
    }

    public void sendRetailVouched(RetailOrder retailOrder){
        //建行生活生成客户返利
        if(retailOrder.getChannel() == null) return;
        if(!"45".equals(retailOrder.getChannel().getId())) return;
        RetailOrderPayMethod orderPayMethod = retailOrderPayMethodRepository.findByOrderId(retailOrder.getId());
        // 发送客户返利
        Map map = MapUtil.mapper("CHANNEL_ID", retailOrder.getChannel().getId(),"COMPANY_ID",retailOrder.getCompany().getId(),
                "CUSTOMER_ID",orderPayMethod.getCustomer().getId(),"OPERATION", retailOrder.getCompany().getParty().getCorporate().getOperation().getId(),
                "RETAIL_ORDER_ID",retailOrder.getId(),"ORDER_TYPE",retailOrder.getOrderType(),"ACTUAL_AMOUNT",retailOrder.getActualAmount());
        com.apestech.framework.json.JSONObject pop = employeeCommissionService.getStrategy(map, "POP");
        if (pop.get("sys_break") != null && pop.get("sys_break").equals("1")) return;
        map.putAll(pop);
        sendSynEvent("event:scene.income.create", map);
    }

    /***
     * 获取可用额度
     * @return
     */
    public Map<String, Double> getCurAmount(SimpleRequest request) {
        JSONObject tempJson = request.getJO();
        String id = tempJson.getJSONObject("dept").getString("id");
        Dept dept = deptRepository.findOne(id);
        if (Objects.isNull(dept)) {
            throw new RuntimeException("未找到对应的门店信息,门店编码:"+id);
        }
        PartyRole company = dept.getCompany();
        if (Objects.isNull(company)) {
            throw new RuntimeException("该门店未配置对应的所属公司!!!");
        }

        // 查询客户 Party
        PartyRole partner = new PartyRole();
        String customerId = tempJson.getJSONObject("customer").getString("id");
        partner.setId(customerId);
        PartyRole partyRole = SpringManager.getBean(PartyRoleRepository.class).findOne(customerId);
        if (partyRole != null) {
            partner = partyRole;
        }

        Map<String, Double> curAmount = getCurAmount(company, partner);
        if (partner.getParty()!=null && partner.getParty().isRole("Company")) {
            curAmount.put("curBalance", 999999D);
            curAmount.put("period", 999999D);
        }

        //新增检查客户账期,应APP要求超账期或者没有账期都返回0
        checkPartnerAccountPeriod(company, partner,curAmount.get("period"),curAmount);
        //获取赋能对平台的额度
        curAmount.putAll(findFnToPlatformCurAmount(company));
        return curAmount;
    }

    private Map<String, Double> findFnToPlatformCurAmount(PartyRole company) {
        List<FnContract> fnContracts = SpringManager.getBean(FnContractRepository.class).qryValidFnContract(company.getId());
        Map<String, Double> curAmount = new HashMap<>();
        if (fnContracts.isEmpty()){
            //未签赋能合同
            curAmount.put("platformPeriod",999999D);
            curAmount.put("platformCurBalance",999999D);
        }else {
            FnContract fnContract = fnContracts.get(0);
            Map<String, Double> platform = getCurAmount(fnContract.getCompany(),company);
            checkPartnerAccountPeriod(fnContract.getCompany(), company,platform.get("period"),platform);
//            curAmount.put("platformPeriod",platform.get("period"));
            //不适用账期
            curAmount.put("platformPeriod",999999D);
            curAmount.put("platformCurBalance",platform.get("curBalance"));
        }
        return curAmount;
    }

    public Map<String, Double> getCurAmount(PartyRole company,  PartyRole partner) {
        Map<String, Double> returnMap = new HashMap<>();
        Map<String, Double> ledgerSummary = ledgerService.summary(MapUtil.mapper("company",company,"partner", partner));
        ledgerSummary.putIfAbsent("credit", 0.00);
        ledgerSummary.putIfAbsent("prepayment_unsettled", 0.00);
        ledgerSummary.putIfAbsent("current_unsettled", 0.00);
        ledgerSummary.putIfAbsent("period", 0.00);
        returnMap.put("curBalance", ledgerSummary.get("credit") + ledgerSummary.get("prepayment_unsettled") - ledgerSummary.get("current_unsettled"));
        returnMap.put("period", ledgerSummary.get("period"));
        return returnMap;
    }

    /**
     * 检查客户账期
     */
    public void checkPartnerAccountPeriod(PartyRole company,  PartyRole partner, Double period, Map<String, Double> curAmount){
        if (period != 0){
            Invoice invoice = invoiceRepository.findFirstByCompanyIdAndPartnerId(company.getId(), partner.getId());
            if (invoice != null){
                Date now = DateUtil.dateToDate(new Date(),DateUtil.SHOW_DATE_FORMAT);
                Date createDate = DateUtil.dateToDate(invoice.getCreateDate(),DateUtil.SHOW_DATE_FORMAT);
                long betweenDays = (now.getTime() - createDate.getTime()) / (1000L*3600L*24L) - 1;
                if (betweenDays > period) curAmount.put("period",0.00);
            }
        }
    }


    private JSONArray getConditionMap(SimpleRequest request){
        JSONObject jo = request.getJO();
        if(jo.containsKey("condition")) return (JSONArray)jo.get("condition");
        return null;
    }

    private String getValueByMatchCondition(JSONArray conditions,String field,String operator){
        for (Object condition : conditions) {
            if(!(condition instanceof Map)) continue;
            Map conditionMap = (Map) condition;
            if(conditionMap.get("field").equals(field) && conditionMap.get("operator").equals(operator)){
                return conditionMap.get("value").toString();
            }
        }
        return null;
    }

    private Date dateFormDate(String dateString){
        if (dateString == null) return null;
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            return simpleDateFormat.parse(dateString);
        }catch (Exception e){
            return null;
        }
    }

    private List<String> orderSource(String order){
        if (order == null) return null;
        List<String> result = new ArrayList<>();
        // 订单可能为服务单或定损单
        if (lossQuotationRepository.findOne(order) != null) {
            // 定损单： 根据定损单查找服务单
            result = servicePlanRepository.findAllBySourceFrom(order).stream()
                    .map(item -> {
                        RetailOrder retailOrder = orderRepository.findByOrigin(item.getId());
                        return retailOrder == null ? null : retailOrder.getId();
                    })
                    .collect(Collectors.toList());
        } else if (servicePlanRepository.findOne(order) != null){
            // 服务单： 根据服务方案单查询零售单
            RetailOrder retailOrder = orderRepository.findByOrigin(order);
            result.add(retailOrder == null ? null : retailOrder.getId());
        } else {
            result.add(order);
        }
        List<String> returnResult = result.stream().filter(item -> item != null).collect(Collectors.toList());
        if (returnResult.isEmpty()) {
            returnResult.add(order);
        }
        return returnResult;
    }

    private JSONObject getParameter(SimpleRequest request){
        JSONObject result = new JSONObject();
        JSONArray conditions = getConditionMap(request);
        // 查询条件
        if(conditions != null) {
            List<String> ids = orderSource(getValueByMatchCondition(conditions,"id","EQ"));
            String carLicense = getValueByMatchCondition(conditions,"carLicense","EQ");
            String dateApproveBeginDate = getValueByMatchCondition(conditions,"dateApprove","GTE");
            String dateApproveEndDate = getValueByMatchCondition(conditions,"dateApprove","LTE");
            String deptId = getValueByMatchCondition(conditions,"deptId","EQ");
            if(ids != null && !ids.isEmpty()) result.put("ids",ids);
            if(carLicense != null) result.put("carLicense",carLicense);
            if(dateApproveBeginDate != null) result.put("dateApproveBeginDate",dateApproveBeginDate);
            if(dateApproveEndDate != null) result.put("dateApproveEndDate",dateApproveEndDate);
            if(deptId != null) result.put("deptId",deptId);
        }else if(request.getJO().containsKey("key")){
            result.put("id",request.get("key"));
        }
        // 分页条件
        JSONObject jo = request.getJO();
        Integer page = jo.getInteger("page");
        Integer size = jo.getInteger("size");
        // 从(page * size) + 1  到 (page + 1) * size
        int minIndex = (page * size) + 1;
        int maxIndex = (page + 1) * size;
        result.put("minIndex",minIndex);
        result.put("maxIndex",maxIndex);
        return result;
    }

    public Map findByRetailOrderMap(SimpleRequest request){
        JSONObject response = new JSONObject();
        // 入参准备
        JSONObject param = getParameter(request);
        //查询
        JSONArray content = retailOrderDao.retailOrderByPage(param);
        JSONArray total = retailOrderDao.retailOrderByPageTotal(param);
        // 封装响应结果
        wrapResponse(response,content,total,request);
        return response;
    }

    private void wrapResponse(JSONObject response,JSONArray content,JSONArray totalJSONArray,SimpleRequest request){
        int size = request.getJO().getInteger("size");
        int total = ((JSONObject) totalJSONArray.get(0)).getInteger("TOTAL");
        int pages = total % size == 0 ? total / size : (total / size) + 1;
        int elements = content.size();
        int page = request.getJO().getInteger("page");
        response.put("total",total);
        response.put("pages",pages);
        response.put("size", size);
        response.put("elements",elements);
        response.put("page",page);
        response.put("content",content);
    }
    public Double findDiscountByOriginOrSource(SimpleRequest request){
        JSONObject jo = request.getJO();
        RetailOrder retailOrder = SpringManager.getBean(RetailOrderRepository.class).findByOriginOrSourceAndOrderTypeNotIn(jo.getString("origin"),jo.getString("source"), Collections.singletonList("paymentUpdate"));
        double discount = 0D;
        if (retailOrder!=null){
            List<RetailOrderExtension> retailOrderExtensions = SpringManager.getBean(RetailOrderExtensionRepository.class).findAllByRetailOrderId(retailOrder.getId());
            discount = retailOrderExtensions.stream().mapToDouble(RetailOrderExtension::getRetailDiscountAmount).sum();
        }
        return discount;
    }
    private JSONArray queryCarAccidentPayInfo(SimpleRequest simpleRequest){
        JSONObject jo = simpleRequest.getJO();
        JSONArray jsonArray = retailOrderDao.queryCarAccidentPayInfo(jo);
        return jsonArray;
    }
    public RetailOrder findRetailOrderByOriginOrSource(SimpleRequest request){
        return SpringManager.getBean(RetailOrderRepository.class).findByOriginOrSourceAndOrderTypeNotIn(request.get("source"),request.get("source"), Collections.singletonList("paymentUpdate"));
    }

}
